
#include "../include/mod_javascript.h"

static int mod_javascript_handler (request_rec *r) {
  /*set up global JS variables, including global and custom objects */

  JSVersion  version;
  JSRuntime *runtime;
  JSContext *context;
  JSObject  *global;
  JSBool     builtins;
  JSClass    global_class = {
    "global", 0,
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
  };
  char      *script;
  jsval      return_value;
  JSString  *str;
  JSBool     ok;

  mod_javascript_config *config;
  mod_javascript_config *request_config = ap_get_module_config(r->per_dir_config, &javascript_module);
  mod_javascript_config *server_config = ap_get_module_config(r->server->module_config, &javascript_module);
  
  if (request_config->enabled == DISABLED) {
    return DECLINED;
  }
  else if (request_config->enabled == ENABLED) {
    config = request_config;
  }
  else if (server_config->enabled == ENABLED) {
    config = server_config;
  }
  else {
    return DECLINED;
  }

  /*
  The debian version of SpiderMonkey is not compiled with UTF8 on :'(
  if (! JS_StringsAreUTF8()) {
    fprintf(stderr, "SpiderMonkey javascript engine not compiled with UTF8 support.\n");
    fflush(stderr);
    return HTTP_INTERNAL_SERVER_ERROR;
  }
  */

  /*  if (strcmp(r->handler, MODULE)) {
    return HTTP_DECLINED;
  }
  */
  r->content_type = "text/plain";
  
  runtime = JS_NewRuntime(8L * 1024L * 1024L);
  if (!runtime) {
    ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
                 "%s could not create runtime", MODULE);
    return HTTP_INTERNAL_SERVER_ERROR;
  }

  context = JS_NewContext(runtime, 8192);

  if (context == NULL) {
    ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
                 "%s could not create context", MODULE);
    return HTTP_INTERNAL_SERVER_ERROR;
  }

  global = JS_NewObject(context, &global_class, NULL, NULL); 

  builtins = JS_InitStandardClasses(context, global);

  script = "'Hello' + ' World! (from js)';";

  ok = JS_EvaluateScript(context, global, script, strlen(script),
                         "blah blah", 1, &return_value);

  if (!r->header_only)
    ap_rputs(JS_GetStringBytes(JS_ValueToString(context, return_value)), r);

  return OK;
}

static void mod_javascript_register_hooks (apr_pool_t *p) {
  ap_hook_handler(mod_javascript_handler, NULL, NULL, APR_HOOK_LAST);
}

//static const char * cmd_timeout(cmd_parms *cmd, void* pconfig, const char *strtimeout)

static const char * set_mod_javascript_handler (cmd_parms *params, void* pconfig, const char *arg) {
  mod_javascript_config *config;

  if (params->path == NULL) {
    config = ap_get_module_config(
      params->server->module_config,
      &javascript_module
    );
  }
  else {
    config = pconfig;
  }
  
  config->handler = (char *) arg;
  config->enabled = ENABLED;
  return NULL;
}

static const command_rec mod_javascript_cmds[] = {
  AP_INIT_TAKE1(
    "JavascriptHandler",
    set_mod_javascript_handler,
    NULL,
    RSRC_CONF|ACCESS_CONF,
    "JavascriptHandler (string) /path/to/javascript/handler.js"
  ),
  {NULL}
};

static void *create_mod_javascript_config (apr_pool_t *p, server_rec *s) {
  mod_javascript_config *new_config;

  new_config = (mod_javascript_config *) apr_pcalloc(p, sizeof(mod_javascript_config));

  new_config->enabled = UNSET;
  new_config->handler = "";

  return (void *) new_config;
}

module AP_MODULE_DECLARE_DATA javascript_module = {
  STANDARD20_MODULE_STUFF,
  create_mod_javascript_config,
  NULL,
  create_mod_javascript_config,
  NULL,
  mod_javascript_cmds,
  mod_javascript_register_hooks,
};

